package com.imhouxy.springTemplateQuery.query;


import lombok.Getter;
import lombok.Setter;
import org.nutz.lang.Strings;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class QueryWrapper implements Criteria {
    private Relation relation = Relation.AND;
    private List<Criteria> list = new ArrayList<>();
    private List<String> orders = new ArrayList<>();
    @Getter
    @Setter
    private long curPage = 1;
    @Getter
    @Setter
    private long pageSize = 10;

    private QueryWrapper() {
    }

    public QueryWrapper orderAsc(String column){
        orders.add(column + " asc ");
        return this;
    }

    public QueryWrapper orderDesc(String column){
        orders.add(column + " desc ");
        return this;
    }

    public String getOrderBy(){
        return Strings.join(",",orders);
    }


    public static QueryWrapper and() {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.relation = Relation.AND;
        return wrapper;
    }

    public static QueryWrapper or() {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.relation = Relation.OR;
        return wrapper;
    }

    @Override
    public String sqlFragment() {
        List<String> frag = new ArrayList<>();
        for (Criteria criteria : list) {
            if(criteria instanceof QueryWrapper){
                frag.add(" ( " + criteria.sqlFragment() + " ) ");
            }else{
                frag.add(criteria.sqlFragment());
            }
        }

        return String.join(relation.getSymbol(), frag);
    }

    @Override
    public Map<String, Object> param() {
        return list.stream()
                .flatMap(criteria -> criteria.param().entrySet().stream())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    private enum Relation {
        AND(" and "), OR(" or ");
        @Getter
        private String symbol;

        Relation(String symbol) {
            this.symbol = symbol;
        }
    }

    public QueryWrapper eq(String column, Object value) {
        Criteria criteria = Condition.eq(column, value);
        this.list.add(criteria);

        return this;
    }

    public QueryWrapper ne(String column, Object value) {
        this.list.add(Condition.ne(column, value));
        return this;
    }

    public QueryWrapper like(String column, Object value) {
        this.list.add(Condition.like(column, value));
        return this;
    }

    public QueryWrapper start(String column, Object value) {
        this.list.add(Condition.start(column, value));
        return this;
    }

    public QueryWrapper end(String column, Object value) {
        this.list.add(Condition.end(column, value));
        return this;
    }

    public QueryWrapper ge(String column, Object value) {
        this.list.add(Condition.ge(column, value));
        return this;
    }

    public QueryWrapper gt(String column, Object value) {
        this.list.add(Condition.gt(column, value));
        return this;
    }

    public QueryWrapper le(String column, Object value) {
        this.list.add(Condition.le(column, value));
        return this;
    }

    public QueryWrapper lt(String column, Object value) {
        this.list.add(Condition.lt(column, value));
        return this;
    }

    public QueryWrapper isNull(String column) {
        this.list.add(Condition.isNull(column));
        return this;
    }

    public QueryWrapper notNull(String column) {
        this.list.add(Condition.notNull(column));
        return this;
    }

    public QueryWrapper sql(String sql) {
        this.list.add(Condition.sql(sql));
        return this;
    }

    public QueryWrapper wrapper(Criteria criteria) {
        this.list.add(criteria);
        return this;
    }


}
